#include "graphsupporttest/TestBaseGraph.h"

#include "boosttestsupport.h"
#include "accumulsupport/AccumulSupport.h"

#include "graphsupport/graph/FacilitiesGraph.h"

void TestCycleGraphCreate()
{
	int n = 30;
	Graph cgr( n );
	BOOST_CHECK( n == cgr.getVertexCount() );

	Graph::AdjMatrixType adjm = cgr.getAdjacentMatrixArr();
	for ( int i = 0; i < n; i++ )
	{
		int j = ( i + 1 ) % n;
		adjm[i][j] = 0.0;
	}

	int cycLength = 0;
	int begVert = 0;
	int curVert = begVert;
	do
	{
		int dest = -1;
		for ( int i = 0; i < n; i++ )
		{
			if ( cgr.existsEdge( curVert, i ) )
			{
				dest = i;
			}
		}
		BOOST_CHECK( dest > -1 );
		if ( dest < 0 )
		{
			break;
		}
		cycLength++;
		curVert = dest;
	} while ( curVert != begVert );

	BOOST_CHECK( n == cycLength );

	for ( int i = 0; i < n; i++ )
	{
		for ( int j = 0; j < n; j++ )
		{
			bool exists = cgr.existsEdge( i, j );
			bool expExist = ( j - i + n ) % n == 1;
			BOOST_CHECK( exists == expExist );
		}
	}
}

void TestGraphCopy()
{
	int citiesCount = 9;
	int facilitiesCount = 7;
	boost::shared_ptr< FacilitiesGraph > fgraph( new FacilitiesGraph( citiesCount, facilitiesCount ) );
	for ( int i = 0; i < facilitiesCount; i++ )
	{
		fgraph->facilitiesPrices[i] = i + 100;
	}
	Graph::AdjMatrixType adjMatr = fgraph->getAdjacentMatrixArr();
	for ( int i = 0; i < citiesCount; i++ )
	{
		for ( int j = 0; j < citiesCount; j++ )
		{
			adjMatr[i][j] = i * 100 + j;
		}
	}
	BOOST_CHECK_EQUAL(
		std::string( "100, 101, 102, 103, 104, 105, 106" ),
		COLL_TO_STRING( fgraph->facilitiesPrices )
	);
	BOOST_CHECK_EQUAL(
		std::string( "0, 1, 2, 3, 4, 5, 6\n" ) +
		std::string( "100, 101, 102, 103, 104, 105, 106\n" ) +
		std::string( "200, 201, 202, 203, 204, 205, 206\n" ) +
		std::string( "300, 301, 302, 303, 304, 305, 306\n" ) +
		std::string( "400, 401, 402, 403, 404, 405, 406\n" ) +
		std::string( "500, 501, 502, 503, 504, 505, 506\n" ) +
		std::string( "600, 601, 602, 603, 604, 605, 606\n" ) +
		std::string( "700, 701, 702, 703, 704, 705, 706\n" ) +
		std::string( "800, 801, 802, 803, 804, 805, 806" ),
		MATR_ARR_TO_STRING( adjMatr, citiesCount, facilitiesCount )
	);

	Graph gr0 = * fgraph;
	BiGraph gr1 = * fgraph;
	FacilitiesGraph gr2 = * fgraph;
	fgraph.reset( ( FacilitiesGraph * ) 0 );

	BOOST_CHECK_EQUAL(
		std::string( "0, 1, 2, 3, 4, 5, 6\n" ) +
		std::string( "100, 101, 102, 103, 104, 105, 106\n" ) +
		std::string( "200, 201, 202, 203, 204, 205, 206\n" ) +
		std::string( "300, 301, 302, 303, 304, 305, 306\n" ) +
		std::string( "400, 401, 402, 403, 404, 405, 406\n" ) +
		std::string( "500, 501, 502, 503, 504, 505, 506\n" ) +
		std::string( "600, 601, 602, 603, 604, 605, 606\n" ) +
		std::string( "700, 701, 702, 703, 704, 705, 706\n" ) +
		std::string( "800, 801, 802, 803, 804, 805, 806" ),
		MATR_ARR_TO_STRING( gr0.getAdjacentMatrixArr(), citiesCount, facilitiesCount )
	);

	BOOST_CHECK_EQUAL( citiesCount, gr1.getFirstBipart() );
	BOOST_CHECK_EQUAL( facilitiesCount, gr1.getSecondBipart() );

	BOOST_CHECK_EQUAL(
		std::string( "100, 101, 102, 103, 104, 105, 106" ),
		COLL_TO_STRING( gr2.facilitiesPrices )
	);
	BOOST_CHECK_EQUAL(
		std::string( "0, 1, 2, 3, 4, 5, 6\n" ) +
		std::string( "100, 101, 102, 103, 104, 105, 106\n" ) +
		std::string( "200, 201, 202, 203, 204, 205, 206\n" ) +
		std::string( "300, 301, 302, 303, 304, 305, 306\n" ) +
		std::string( "400, 401, 402, 403, 404, 405, 406\n" ) +
		std::string( "500, 501, 502, 503, 504, 505, 506\n" ) +
		std::string( "600, 601, 602, 603, 604, 605, 606\n" ) +
		std::string( "700, 701, 702, 703, 704, 705, 706\n" ) +
		std::string( "800, 801, 802, 803, 804, 805, 806" ),
		MATR_ARR_TO_STRING( gr2.getAdjacentMatrixArr(), gr2.getCitiesCount(), gr2.getFacilitiesCount() )
	);

	fgraph.reset( new FacilitiesGraph( 3, 3 ) );
	fgraph->getAdjacentMatrixArr()[1][1] = 123.0;
	fgraph->facilitiesPrices[1] = 456.0;
	BOOST_CHECKPOINT( "pre-copy" );
	gr2 = * fgraph;
	fgraph->getAdjacentMatrixArr()[1][1] = 333.0;
	fgraph.reset( ( FacilitiesGraph * ) 0 );

	BOOST_CHECK_EQUAL( 6, gr2.getVertexCount() );
	BOOST_CHECK_EQUAL( 123.0, gr2.getAdjacentMatrixArr()[1][1] );
	BOOST_CHECK_EQUAL( 3, gr2.getFirstBipart() );
	BOOST_CHECK_EQUAL( 456.0, gr2.facilitiesPrices[1] );
}

void TestFacilitiesGraph()
{
	FacilitiesGraph::FacilityPriceType EPS = 1e-5;

	int n = 100;
	int citiecCount = 70;
	int facilitiesCount = n - citiecCount;
	FacilitiesGraph fgraph( citiecCount, facilitiesCount );

	BOOST_CHECK_EQUAL( fgraph.getFirstBipart(), citiecCount );
	BOOST_CHECK_EQUAL( fgraph.getSecondBipart(), facilitiesCount );

	Graph::AdjMatrixType adjMatr = fgraph.getAdjacentMatrixArr();
	adjMatr[56][78] = 123.0;

	BOOST_CHECK_EQUAL( n, fgraph.getVertexCount() );
	BOOST_CHECK_CLOSE( 123.0, fgraph.getFSEdge( 56, 78 - citiecCount ), EPS );
	BOOST_CHECK_EQUAL( facilitiesCount, fgraph.facilitiesPrices.size() );
}
